package com.jswlw.common.wx;

import com.jswlw.common.BaseException;
import com.jswlw.common.ResponseStatus;
import com.jswlw.common.utils.UUIDUtils;
import com.jswlw.common.utils.XmlUtils;
import com.jswlw.config.DefaultHttpClient;
import com.jswlw.controller.api.req.wx.WxPayRequest;
import com.jswlw.controller.api.resp.UnifiedOrderResponse;
import com.jswlw.controller.distributor.resp.UnifiedOrderData;
import com.jswlw.web.manager.SessionApiManager;
import com.sun.xml.internal.ws.transport.Headers;
import lombok.extern.slf4j.Slf4j;
import okhttp3.MediaType;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import java.util.HashMap;
import java.util.Map;
import java.util.SortedMap;

@Slf4j
@Component
public class WxPayHelper {

    public static final MediaType JSON_MEDIA_TYPE = MediaType.parse("text/xml; charset=utf-8");

    @Value("${wx.app.appId}")
    private String appId;

    @Value("${wx.app.mchId}")
    private String mchId;

    @Value("${wx.app.signKey}")
    private String signKey;

    @Value("${wx.app.notifyUrl}")
    private String notifyUrl;

    @Autowired
    DefaultHttpClient httpClient;

    public UnifiedOrderResponse unifiedorder(WxPayRequest payRequest, String ip) {
        UnifiedOrderResponse result = new UnifiedOrderResponse();


        String nonce_str = UUIDUtils.uuid32();
        String orderId = payRequest.getSn();
        String body = payRequest.getBody();
        String openId = SessionApiManager.getCurrentUser();
        String totalFee = payRequest.getTotalFee();

        SortedMap signParams = new Headers();
        signParams.put("appid", appId);
        signParams.put("mch_id", mchId);
        signParams.put("nonce_str", nonce_str);
        signParams.put("body", body);
        signParams.put("out_trade_no", orderId);
        signParams.put("total_fee", (int) (Double.parseDouble(totalFee)) + "");
        signParams.put("spbill_create_ip", ip);
        signParams.put("notify_url", notifyUrl);
        signParams.put("trade_type", "JSAPI");
        signParams.put("openid", openId);
        log.info("下单参数:" + signParams);
        String sign = SignUtil.createSign(signKey, signParams);

        SortedMap params = new Headers();
        params.put("appid", appId);
        params.put("mch_id", mchId);
        params.put("nonce_str", nonce_str);
        params.put("body", body);
        params.put("out_trade_no", orderId);
        params.put("total_fee", (int) (Double.parseDouble(totalFee)) + "");
        params.put("spbill_create_ip", ip);
        params.put("notify_url", notifyUrl);
        params.put("trade_type", "JSAPI");
        params.put("openid", openId);
        log.info("下单参数:" + params);
        try {
            RequestBody requestBody = RequestBody.create(JSON_MEDIA_TYPE, SignUtil.parseString2Xml(params, sign));

            Request request = new Request.Builder()
                    .url(WeiXinConstant.UNIFIEORDER)
                    .post(requestBody)
                    .build();
            Response response = httpClient.newCall(request).execute();
            Map apiRetMap = XmlUtils.readStringXmlOut(response.body().string());
            log.error("下单结果:" + apiRetMap);
            if (WeiXinConstant.PAY_SUCCESS.equals(apiRetMap.get("return_code"))) {
                Map<String, Object> reSignParams = new HashMap<>();
                reSignParams.put("appId", appId + "");
                reSignParams.put("timeStamp", SignUtil.timeStamp() + "");
                reSignParams.put("nonceStr", nonce_str);
                reSignParams.put("package", "prepay_id=" + apiRetMap.get("prepay_id") + "");
                reSignParams.put("signType", "MD5");
                String reSign = SignUtil.createSign(signKey, SignUtil.map2SortedMap(reSignParams));
                reSignParams.put("paySign", reSign);
                log.info("重新签名参数:" + reSign);
                UnifiedOrderResponse.UnifiedOrderData data = new UnifiedOrderResponse.UnifiedOrderData();
                data.setNonceStr(nonce_str);
                data.setPaySign(reSign);
                data.setPrepay_id(apiRetMap.get("prepay_id") + "");
                data.setTimeStamp(String.valueOf(reSignParams.get("timeStamp")));
                result.setData(data);
                result.success();
                return result;
            } else {
                result.setCode(ResponseStatus.BUSINESS_ERROR.getCode());
                result.setMsg("下单失败");
            }

        } catch (Exception e) {
            log.error("下单错误", e);
        }
        result.setCode(ResponseStatus.BUSINESS_ERROR.getCode());
        result.setMsg("下单失败");
        return result;
    }

    public UnifiedOrderData unifiedorderJsp(WxPayRequest payRequest, String ip) {
        String nonce_str = UUIDUtils.uuid32();
        String orderId = payRequest.getSn();
        String body = payRequest.getBody();
        String openId = "orMZC1u42UCwGGPvweq4XGRkM4e4";
        String totalFee = payRequest.getTotalFee();

        SortedMap signParams = new Headers();
        signParams.put("appid", appId);
        signParams.put("mch_id", mchId);
        signParams.put("nonce_str", nonce_str);
        signParams.put("body", body);
        signParams.put("out_trade_no", orderId);
        signParams.put("total_fee", (int) (Double.parseDouble(totalFee) * 100) + "");
        signParams.put("spbill_create_ip", ip);
        signParams.put("notify_url", notifyUrl);
        signParams.put("trade_type", "JSAPI");
        signParams.put("openid", openId);
        log.info("下单参数:" + signParams);
        String sign = SignUtil.createSign(signKey, signParams);

        SortedMap params = new Headers();
        params.put("appid", appId);
        params.put("mch_id", mchId);
        params.put("nonce_str", nonce_str);
        params.put("body", body);
        params.put("out_trade_no", orderId);
        params.put("total_fee", (int) (Double.parseDouble(totalFee) * 100) + "");
        params.put("spbill_create_ip", ip);
        params.put("notify_url", notifyUrl);
        params.put("trade_type", "JSAPI");
        params.put("openid", openId);
        log.info("下单参数:" + params);
        try {
            RequestBody requestBody = RequestBody.create(JSON_MEDIA_TYPE, SignUtil.parseString2Xml(params, sign));

            Request request = new Request.Builder()
                    .url(WeiXinConstant.UNIFIEORDER)
                    .post(requestBody)
                    .build();
            Response response = httpClient.newCall(request).execute();
            Map apiRetMap = XmlUtils.readStringXmlOut(response.body().string());
            log.error("下单结果:" + apiRetMap);
            if (WeiXinConstant.PAY_SUCCESS.equals(apiRetMap.get("return_code"))) {
                Map<String, Object> reSignParams = new HashMap<>();
                reSignParams.put("appId", appId + "");
                reSignParams.put("timeStamp", SignUtil.timeStamp() + "");
                reSignParams.put("nonceStr", nonce_str);
                reSignParams.put("package", "prepay_id=" + apiRetMap.get("prepay_id") + "");
                reSignParams.put("signType", "MD5");
                String reSign = SignUtil.createSign(signKey, SignUtil.map2SortedMap(reSignParams));
                reSignParams.put("paySign", reSign);
                log.info("重新签名参数:" + reSign);
                UnifiedOrderData data = new UnifiedOrderData();
                data.setNonceStr(nonce_str);
                data.setPaySign(reSign);
                data.setPrepay_id(apiRetMap.get("prepay_id") + "");
                data.setTimeStamp(String.valueOf(reSignParams.get("timeStamp")));
                return data;
            } else {
                BaseException.sneakyThrows(ResponseStatus.BUSINESS_ERROR.getCode(), "下单失败");
            }

        } catch (Exception e) {
            log.error("下单错误", e);
        }
        BaseException.sneakyThrows(ResponseStatus.BUSINESS_ERROR.getCode(), "下单失败");
        return null;
    }
}
